from sqlmodel import Session, Field, select, and_, or_
from dependencies import engine, SessionDep
from typing import Union, List, Optional, Any
from common import exception
import models
import utility
import datetime



"""查询量表详情

Keyword arguments:
scale_id -- 量表详情id
status -- 量表详情状态
session -- 数据库连接
Return: scale_detail -- 量表详情数据
"""

def get_scale_detail(
    scale_id: int | None = None,
    status: int = 0,
    user: models.SystemUser = None,
    session: Optional[SessionDep] = Session(engine),
):
    # 查询量表详情数据
    statement = (
        select(models.ScaleDetail)
        .join(models.Scale, models.ScaleDetail.scale_id == models.Scale.id)
        .join(
            models.ScaleHistory, models.ScaleHistory.detail_id == models.ScaleDetail.id
        )
        .where(
            and_(
                models.ScaleHistory.status == status,
                models.ScaleDetail.scale_id == scale_id,
            )
        )
    )

    scale_detail = session.exec(statement).first()

    # 校验当前量表是否存在
    if not scale_detail:
        raise exception.create_http_exception(status_code=400, detail="量表详情不存在")

    # 初始化返回结果
    result = dict(scale_detail)

    # 校验当前量表是否存在
    if not scale_detail:
        raise exception.create_http_exception(status_code=400, detail="量表详情不存在")

    # 初始化返回结果
    result = dict(scale_detail)

    # 初始化查询量表题目数据
    questions = []
    # 遍历查询量表题目数据
    for question in scale_detail.questions:
        question_dict = dict(question)
        # 单/多选题
        if question.type in [1, 2]:
            options = []
            # 初始化选项关联题目数据
            for option in question.options:
                option_dict = dict(option)
                option_ques_links = [
                    option_ques_link.ques_id
                    for option_ques_link in option.option_ques_links
                    if option.option_ques_links
                ]
                option_dict["option_ques_links"] = option_ques_links
                options.append(option_dict)
            # 将选项数据转化成树状结构
            options = utility.general.build_tree_recursive(options)
            # 选项详情
            question_dict["options"] = options

        # 单/多项填空题
        elif question.type in [3, 4]:
            # 填空详情
            question_dict["blanks"] = [dict(blank) for blank in question.blanks]
        # 单/多维矩阵单选题
        elif question.type in [5, 6]:
            # 矩阵行数据
            question_dict["rows"] = [dict(row) for row in question.rows]
            # 矩阵列数据
            question_dict["columns"] = [dict(column) for column in question.columns]

        # 跳转逻辑列表
        jump_logics = []
        for jump_logic in question.jump_logics:
            jump_logic_dict = dict(jump_logic)
            jump_logic_dict["jump_logic_details"] = [
                dict(jump_logic_detail)
                for jump_logic_detail in jump_logic.jump_logic_details
            ]
            jump_logics.append(jump_logic_dict)
        question_dict["jump_logics"] = jump_logics

        questions.append(question_dict)
    result["questions"] = questions

    return result


"""暂存量表详情

Keyword arguments:
scale_detail -- 暂存量表详情数据
user -- 当前用户
Return: scale_detail_draft
"""


def update_scale_detail(
    scale_detail: models.ScaleDetailUpdate,
    user: models.SystemUser = None,
    session: Optional[SessionDep] = Session(engine),
):
    # 查询量表详情数据
    scale_detail_draft = session.get(models.ScaleDetail, scale_detail.id)

    # 获取量表详情与量表关联数据
    scale_detail_link = session.exec(
        select(models.ScaleHistory).where(
            models.ScaleHistory.detail_id == scale_detail.id
        )
    ).one_or_none()

    # 量表详情状态
    scale_detail_status = scale_detail_link.status

    # 校验当前量表是否存在
    if not scale_detail_draft:
        raise exception.create_http_exception(status_code=400, detail="量表详情不存在")
    # 校验当前量表详情是否为草稿状态
    elif scale_detail_status != 0:
        raise exception.create_http_exception(
            status_code=400, detail="非草稿状态，无法编辑"
        )
    # 校验用户是否有权限编辑当前量表
    elif (
        utility.general.check_data_permission(scale_detail_link.scale.org_id, user, session)
        == False
    ):
        raise exception.create_http_exception(
            status_code=400, detail="用户无编辑量表权限"
        )

    # 新增/编辑量表详情数据
    scale_detail_merge = models.ScaleDetail(
        scale_id=scale_detail.scale_id,
        name=scale_detail.name,
        description=scale_detail.description,
        id=scale_detail.id,
    )

    session.merge(scale_detail_merge)
    session.flush()

    # 删除题目数据
    if scale_detail_draft.questions:
        for exist_question in scale_detail_draft.questions:
            if exist_question.id not in [
                question.id for question in scale_detail.questions
            ]:
                session.delete(exist_question)
                session.flush()

    # 新增/编辑题目数据
    for question in scale_detail.questions:
        question_merge = models.ScaleDetailQues(
            order=question.order,
            type=question.type,
            title=question.title,
            hassubtitle=question.hassubtitle,
            subtitle=question.subtitle,
            required=question.required,
            basic_scale_id=question.basic_scale_id,
            response_logic=question.response_logic,
            id=question.id,
            scale_detail=scale_detail_merge,
        )
        session.merge(question_merge)
        session.flush()

        if question.type in [1, 2]:
            # 拉平选项数据
            options: List[models.ScaleDetailQuesOptionUpdate] = (
                utility.general.flatten_options(question.options)
            )

            # 获取原选项数据
            exist_options = session.exec(
                select(models.ScaleDetailQuesOption).where(
                    models.ScaleDetailQuesOption.scale_detail_ques_id == question.id
                )
            )

            # 删除原选项数据
            for exist_option in exist_options:
                if exist_option.id not in [option.id for option in options]:
                    session.delete(exist_option)
                    session.flush()

            # 新增/编辑选项数据
            for option in options:
                # 新增/编辑选项数据
                option_merge = models.ScaleDetailQuesOption(
                    parent_id=option.parent_id,
                    order=option.order,
                    content=option.content,
                    type=option.type,
                    placeholder=option.placeholder,
                    defaultValue=option.defaultValue,
                    validate_type=option.validate_type,
                    required=option.required,
                    score=option.score,
                    id=option.id,
                    question=question_merge,
                )
                session.merge(option_merge)
                session.flush()

                # 新增/编辑选项关联题目数据
                for option_ques_link in option.option_ques_links:
                    # 查询已存在选项关联题目数据
                    existing_option_ques_link = session.exec(
                        select(models.ScaleDetailOptionQuesLink).where(
                            models.ScaleDetailOptionQuesLink.ques_id
                            == option_ques_link,
                            models.ScaleDetailOptionQuesLink.option_id
                            == option_merge.id,
                        )
                    ).one_or_none()
                    if not existing_option_ques_link:
                        # 新增选项关联题目数据
                        option_ques_link_model = models.ScaleDetailOptionQuesLink(
                            ques_id=option_ques_link,
                            option_id=option_merge.id,
                        )
                        session.add(option_ques_link_model)
                        session.flush()

                # 删除原选项关联题目数据
                for option_ques_link in session.exec(
                    select(models.ScaleDetailOptionQuesLink).where(
                        models.ScaleDetailOptionQuesLink.option_id == option_merge.id
                    )
                ):
                    if option_ques_link.ques_id not in option.option_ques_links:
                        option_ques_link_delete = session.exec(
                            select(models.ScaleDetailOptionQuesLink).where(
                                models.ScaleDetailOptionQuesLink.ques_id
                                == option_ques_link.ques_id,
                                models.ScaleDetailOptionQuesLink.option_id
                                == option_merge.id,
                            )
                        ).one_or_none()
                        session.delete(option_ques_link_delete)

        elif question.type in [3, 4]:
            # 删除原填空数据
            for existing_blank in session.exec(
                select(models.ScaleDetailQuesBlank).where(
                    models.ScaleDetailQuesBlank.scale_detail_ques_id == question.id
                )
            ):
                if existing_blank.id not in [blank.id for blank in question.blanks]:
                    session.delete(existing_blank)
                    session.flush()

            # 新增/编辑填空数据
            for blank in question.blanks:
                # 新增/编辑选项数据
                blank_merge = models.ScaleDetailQuesBlank(
                    id=blank.id,
                    order=blank.order,
                    type=blank.type,
                    placeholder=blank.placeholder,
                    defaultValue=blank.defaultValue,
                    validate_type=blank.validate_type,
                    question=question_merge,
                )
                session.merge(blank_merge)
                session.flush()

        elif question.type in [5, 6]:
            # 获取已关联矩阵单选行数据
            exist_rows = session.exec(
                select(models.ScaleDetailQuesMatrixSingleOptionRow).where(
                    models.ScaleDetailQuesMatrixSingleOptionRow.scale_detail_ques_id
                    == question.id
                )
            )

            # 获取已关联矩阵单选列数据
            exist_columns = session.exec(
                select(models.ScaleDetailQuesMatrixSingleOptionColumn).where(
                    models.ScaleDetailQuesMatrixSingleOptionColumn.scale_detail_ques_id
                    == question.id
                )
            )

            # 删除原矩阵单线行数据
            for exist_row in exist_rows:
                if exist_row.id not in [row.id for row in question.rows]:
                    session.delete(exist_row)
                    session.flush()
            # 删除原矩阵单线列数据
            for exist_column in exist_columns:
                if exist_column.id not in [column.id for column in question.columns]:
                    session.delete(exist_column)
                    session.flush()

            # 新增/编辑矩阵单线行数据
            for row in question.rows:
                # 新增/编辑选项数据
                row_merge = models.ScaleDetailQuesMatrixSingleOptionRow(
                    order=row.order,
                    classify=row.classify,
                    content=row.content,
                    id=row.id,
                    question=question_merge,
                )
                session.merge(row_merge)
                session.flush()

            # 新增/编辑矩阵单线列数据
            for column in question.columns:
                # 新增/编辑选项数据
                column_merge = models.ScaleDetailQuesMatrixSingleOptionColumn(
                    id=column.id,
                    order=column.order,
                    classify=column.classify,
                    content=column.content,
                    score=column.score,
                    question=question_merge,
                )
                session.merge(column_merge)
                session.flush()

        # 获取已关联的跳转逻辑数据
        exist_jump_logics = session.exec(
            select(models.ScaleJumpLogic).where(
                models.ScaleJumpLogic.ques_id == question.id
            )
        )

        # 删除原跳转逻辑数据
        for exist_jump_logic in exist_jump_logics:
            if exist_jump_logic.id not in [
                jump_logic.id for jump_logic in question.jump_logics
            ]:
                session.delete(exist_jump_logic)
                session.flush()

        # 新增/编辑跳转逻辑数据
        for jump_logic in question.jump_logics:
            # 新增/编辑跳转逻辑数据
            jump_logic_merge = models.ScaleJumpLogic(
                next_question_id=jump_logic.next_question_id,
                logic=jump_logic.logic,
                id=jump_logic.id,
                question=question_merge,
            )
            session.merge(jump_logic_merge)
            session.flush()

            # 获取已关联的跳转逻辑详情数据
            exist_jump_logic_details = session.exec(
                select(models.ScaleJumpLogicDetail).where(
                    models.ScaleJumpLogicDetail.jump_logic_id == jump_logic.id
                )
            )

            # 删除原跳转逻辑详情数据
            if exist_jump_logic_details:
                for exist_jump_logic_detail in exist_jump_logic_details:
                    if exist_jump_logic_detail.id not in [
                        jump_logic_detail.id
                        for jump_logic_detail in jump_logic.jump_logic_details
                    ]:
                        session.delete(exist_jump_logic_detail)
                        session.flush()

            # 新增/编辑跳转逻辑详情数据
            for jump_logic_detail in jump_logic.jump_logic_details:
                # 新增/编辑跳转逻辑详情数据
                jump_logic_detail_merge = models.ScaleJumpLogicDetail(
                    ques_id=jump_logic_detail.ques_id,
                    option_id=jump_logic_detail.option_id,
                    line_id=jump_logic_detail.line_id,
                    row_id=jump_logic_detail.row_id,
                    logic=jump_logic_detail.logic,
                    id=jump_logic_detail.id,
                    jump_logic=jump_logic_merge,
                )
                session.merge(jump_logic_detail_merge)
                session.flush()

    session.commit()
    session.refresh(scale_detail_draft)

    return scale_detail_draft


"""复制量表相关数据

Keyword arguments:
scale_detail_id -- 拷贝的量表数据id
session -- 数据库会话
Return: scale_detail_create -- 新增的量表详情数据
"""


def clone_scale_detail(
    scale_detail_id: int,
    session: Optional[SessionDep] = Session(engine),
):
    original_scale_detail = session.get(models.ScaleDetail, scale_detail_id)

    # 拷贝量表详情数据
    new_scale_detail = models.ScaleDetail(
        scale_id=original_scale_detail.scale_id,
        name=original_scale_detail.name,
        description=original_scale_detail.description,
        scale_link=models.ScaleHistory(
            scale_id=original_scale_detail.scale_id,
            status=0,
        ),
        questions=[],  # 初始化空列表
    )
    session.add(new_scale_detail)
    session.flush()

    # 创建一个字典来存储原始问题ID到新问题ID的映射
    question_id_map = {}

    # 深度复制所有关联问题
    option_id_map = {}
    row_id_map = {}
    column_id_map = {}
    for question in original_scale_detail.questions:
        new_question, new_option_id_map, new_row_id_map, new_column_id_map = (
            copy_question(
                question_id=question.id,
                new_scale_detail_id=new_scale_detail.id,
                session=session,
            )
        )
        new_scale_detail.questions.append(new_question)

        question_id_map[question.id] = new_question.id
        option_id_map.update(new_option_id_map)
        row_id_map.update(new_row_id_map)
        column_id_map.update(new_column_id_map)

    # 更新选项关联题目的问题ID为新问题ID
    for question in new_scale_detail.questions:
        if question.options:
            for option in question.options:
                if option.option_ques_links:
                    for option_ques_link in option.option_ques_links:
                        if option_ques_link.ques_id in question_id_map:
                            option_ques_link.ques_id = question_id_map[
                                option_ques_link.ques_id
                            ]
                            session.merge(option_ques_link)
                            session.flush()

        if question.jump_logics:
            # 更新跳转逻辑关联题目的问题ID为新问题ID
            for jump_logic in question.jump_logics:
                # 更新跳转逻辑详情关联题目的问题ID为新问题ID
                if jump_logic.next_question_id in question_id_map:
                    jump_logic.next_question_id = question_id_map[
                        jump_logic.next_question_id
                    ]
                    session.merge(jump_logic)
                    session.flush()

                for jump_logic_detail in jump_logic.jump_logic_details:
                    if jump_logic_detail.ques_id in question_id_map:
                        jump_logic_detail.ques_id = question_id_map[
                            jump_logic_detail.ques_id
                        ]

    # 拷贝量表评分规则详情
    if (
        original_scale_detail.scale_score_rules
        and session.get(models.Scale, original_scale_detail.scale_id).type == 1
    ):
        # 如果量表类型为1（基础量表）且有量表评分规则数据，保存量表评分规则
        for scale_score_rule in original_scale_detail.scale_score_rules:
            new_scale_score_rule = models.ScaleScoreRule(
                scale_detail_id=new_scale_detail.id,
                algorithm=scale_score_rule.algorithm,
            )
            session.add(new_scale_score_rule)
            session.flush()

            if scale_score_rule.algorithm == 1:
                # 如果算法T分，拷贝T分算法详情
                for logic in scale_score_rule.logics:
                    new_logic = models.ScaleScoreRuleLogic(
                        classify=logic.classify,
                        start=logic.start,
                        start_include=logic.start_include,
                        end=logic.end,
                        end_include=logic.end_include,
                        description=logic.description,
                        scale_score_rule_id=new_scale_score_rule.id,
                    )
                    session.add(new_logic)
                    session.flush()
            elif scale_score_rule.algorithm in [2, 3]:
                # 如果算法为维度T分或多维T分，拷贝维度T分或多维T分算法详情
                for dimension in scale_score_rule.dimensions:
                    new_dimension = models.ScaleScoreRuleDimension(
                        name=dimension.name,
                        order=dimension.order,
                        scale_score_rule_id=new_scale_score_rule.id,
                    )
                    session.add(new_dimension)
                    session.flush()

                    for dimensions_ques_link in dimension.dimensions_ques_links:
                        new_dimensions_ques_link = (
                            models.ScaleScoreRuleDimensionQuesLink(
                                ques_id=question_id_map[dimensions_ques_link.ques_id],
                                row_id=row_id_map.get(
                                    dimensions_ques_link.row_id,
                                    dimensions_ques_link.row_id,
                                ),  # 这里需要更新为新的行ID
                                dimension_id=new_dimension.id,
                            )
                        )
                        session.add(new_dimensions_ques_link)
                        session.flush()

                    for logic in dimension.logics:
                        new_logic = models.ScaleScoreRuleLogic(
                            classify=logic.classify,
                            start=logic.start,
                            start_include=logic.start_include,
                            end=logic.end,
                            end_include=logic.end_include,
                            description=logic.description,
                            scale_score_rule_id=new_scale_score_rule.id,
                            dimension_id=new_dimension.id,
                        )
                        session.add(new_logic)
                        session.flush()
            elif scale_score_rule.algorithm == 4:
                # 如果算法为自定义分数，拷贝自定义分数算法详情
                for custom_rule in scale_score_rule.custom_rules:
                    new_custom_rule = models.ScaleScoreRuleCustomRule(
                        name=custom_rule.name,
                        order=custom_rule.order,
                        expression=custom_rule.expression,
                        scale_score_rule_id=new_scale_score_rule.id,
                    )
                    session.add(new_custom_rule)
                    session.flush()

                    for logic in custom_rule.logics:
                        new_logic = models.ScaleScoreRuleLogic(
                            classify=logic.classify,
                            start=logic.start,
                            start_include=logic.start_include,
                            end=logic.end,
                            end_include=logic.end_include,
                            description=logic.description,
                            scale_score_rule_id=new_scale_score_rule.id,
                            custom_rule_id=new_custom_rule.id,
                        )
                        session.add(new_logic)
                        session.flush()
    session.commit()

    return new_scale_detail


"""复制问题数据

Keyword arguments:
question_id -- 需要复制的问题ID
new_scale_detail_id -- 新的量表详情ID
Return: new_scale_detail_question -- 新增的量表详情问题数据
"""


def copy_question(
    question_id: int,
    new_scale_detail_id: int,
    session: Optional[SessionDep] = Session(engine),
):
    question = session.get(models.ScaleDetailQues, question_id)

    # 拷贝问题数据
    new_question = models.ScaleDetailQues(
        order=question.order,
        type=question.type,
        title=question.title,
        hassubtitle=question.hassubtitle,
        subtitle=question.subtitle,
        required=question.required,
        basic_scale_id=question.basic_scale_id,
        response_logic=question.response_logic,
        scale_detail_id=new_scale_detail_id,  # 设置新new_scale_detail_id
        options=[],  # 初始化选项列表
        blanks=[],  # 初始化填空列表
        rows=[],  # 初始化行列表
        columns=[],  # 初始化列列表
        jump_logics=[],  # 初始化跳转逻辑列表
    )
    session.add(new_question)
    session.flush()

    # 创建一个字典来存储原始ID到新ID的映射
    option_id_map = {}  # 选项映射
    row_id_map = {}  # 行映射
    column_id_map = {}  # 列映射

    if question.type in [1, 2] and question.options:
        # 拷贝选项数据
        for option in question.options:
            new_option = models.ScaleDetailQuesOption(
                parent_id=(
                    option_id_map.get(option.parent_id) if option.parent_id else None
                ),
                order=option.order,
                content=option.content,
                type=option.type,
                placeholder=option.placeholder,
                defaultValue=option.defaultValue,
                validate_type=option.validate_type,
                required=option.required,  # 设置 required 字段
                score=option.score,
                question=new_question,
                option_ques_links=[],  # 初始化选项关联题目列表
            )
            session.add(new_option)
            session.flush()

            # 更新映射关系
            option_id_map[option.id] = new_option.id

            if option.option_ques_links:
                # 拷贝选项关联题目
                for option_ques_link in option.option_ques_links:
                    new_option_ques_link = models.ScaleDetailOptionQuesLink(
                        option_id=new_option.id,
                        ques_id=option_ques_link.ques_id,  # 使用新的问题ID
                    )
                    session.add(new_option_ques_link)
                    session.flush()

                    new_option.option_ques_links.append(
                        new_option_ques_link
                    )  # 添加到新的选项对象中

            new_question.options.append(new_option)  # 添加到新的问题对象中

    elif question.type in [3, 4]:
        # 拷贝填空数据
        for blank in question.blanks:
            new_blank = models.ScaleDetailQuesBlank(
                order=blank.order,
                type=blank.type,
                placeholder=blank.placeholder,
                defaultValue=blank.defaultValue,
                validate_type=blank.validate_type,
                question=new_question,
            )
            session.add(new_blank)
            session.flush()

            new_question.blanks.append(new_blank)  # 添加到新的问题对象中

    elif question.type in [5, 6]:
        # 拷贝矩阵单选题行数据
        for row in question.rows:
            new_row = models.ScaleDetailQuesMatrixSingleOptionRow(
                order=row.order,
                classify=row.classify,
                content=row.content,
                question=new_question,
            )
            session.add(new_row)
            session.flush()

            row_id_map[row.id] = new_row.id  # 更新映射关系

            new_question.rows.append(new_row)  # 添加到新的问题对象中

        # 拷贝矩阵单选题列数据
        for column in question.columns:
            new_column = models.ScaleDetailQuesMatrixSingleOptionColumn(
                order=column.order,
                classify=column.classify,
                content=column.content,
                score=column.score,
                question=new_question,
            )
            session.add(new_column)
            session.flush()

            column_id_map[column.id] = new_column.id  # 更新映射关系

            new_question.columns.append(new_column)  # 添加到新的问题对象中

    # 拷贝跳题目逻辑数据
    if question.jump_logics:
        for jump_logic in question.jump_logics:
            new_jump_logic = models.ScaleJumpLogic(
                ques_id=new_question.id,  # 设置新的问题ID
                next_question_id=jump_logic.next_question_id,
                logic=jump_logic.logic,
                jump_logic_details=[],  # 初始化跳题目逻辑详情列表
            )
            session.add(new_jump_logic)
            session.flush()

            # 拷贝跳题目逻辑详情
            for jump_logic_detail in jump_logic.jump_logic_details:
                new_jump_logic_detail = models.ScaleJumpLogicDetail(
                    jump_logic_id=new_jump_logic.id,  # 设置新的跳题目逻辑ID
                    logic=jump_logic_detail.logic,
                    line_id=row_id_map.get(
                        jump_logic_detail.line_id, jump_logic_detail.line_id
                    ),
                    row_id=row_id_map.get(
                        jump_logic_detail.row_id, jump_logic_detail.row_id
                    ),
                    option_id=option_id_map.get(
                        jump_logic_detail.option_id, jump_logic_detail.option_id
                    ),
                    ques_id=new_question.id,  # 设置新的问题ID
                )
                session.add(new_jump_logic_detail)
                session.flush()

                new_jump_logic.jump_logic_details.append(
                    new_jump_logic_detail
                )  # 添加到新的跳题目逻辑对象中

        new_question.jump_logics.append(new_jump_logic)  # 添加到新的问题对象中

    return new_question, option_id_map, row_id_map, column_id_map


"""查询量表评分规则

Keyword arguments:
scale_detail_id -- 量表详情id
Return: result -- 量表评分规则数据
"""


def get_scale_score_rule(
    scale_detail_id: int,
    session: Optional[SessionDep] = Session(engine),
):
    # 校验量表详情id是否存在
    if not session.get(models.ScaleDetail, scale_detail_id):
        raise exception.create_http_exception(status_code=404, detail="量表详情不存在")

    # 初始化返回结果
    result = []

    # 查询量表评分规则数据
    rules = session.exec(
        select(models.ScaleScoreRule).where(
            models.ScaleScoreRule.scale_detail_id == scale_detail_id
        )
    ).all()

    # 遍历量表评分规则数据
    for rule in rules:
        # 规则字典
        rule_dict = dict(rule)

        if rule.algorithm == 1:
            # 查询量表评分计算规则逻辑列表
            rule_logics = [dict(logic) for logic in rule.logics]

            rule_dict["logics"] = rule_logics

        elif rule.algorithm in [2, 3]:
            # 初始化dimensions
            dimensions = []

            # 遍历量表评分计算规则维度列表
            for dimension in rule.dimensions:
                # 初始化dimension_dict
                dimension_dict = dict(dimension)

                dimension_logics = [
                    dict(logic) for logic in dimension.logics
                ]  # 维度关联的量表评分计算规则逻辑列表
                dimensions_ques_links = [
                    dict(link) for link in dimension.dimensions_ques_links
                ]  # 维度关联的量表详情题目或者行列表

                # 添加维度关联的量表评分计算规则逻辑列表和量表详情题目或者行列表到dimension_dict
                dimension_dict["logics"] = dimension_logics
                dimension_dict["dimensions_ques_links"] = dimensions_ques_links

                # 添加dimension_dict到dimensions
                dimensions.append(dimension_dict)

            # 添加dimensions到rule_dict
            rule_dict["dimensions"] = dimensions

        elif rule.algorithm == 4:
            # 初始化custom_rules
            custom_rules = []

            # 遍历量表评分计算规则自定义规则列表
            for custom_rule in rule.custom_rules:
                # 初始化custom_rule_dict
                custom_rule_dict = dict(custom_rule)

                custom_rule_logics = [
                    dict(logic) for logic in custom_rule.logics
                ]  # 自定义规则关联的量表评分计算规则逻辑列表

                # 添加自定义规则关联的量表评分计算规则逻辑列表到custom_rule_dict
                custom_rule_dict["logics"] = custom_rule_logics

                # 添加custom_rule_dict到custom_rules
                custom_rules.append(custom_rule_dict)

            # 添加custom_rules到rule_dict
            rule_dict["custom_rules"] = custom_rules

        result.append(rule_dict)

    return result


"""编辑或更新量表评分规则

Keyword arguments:
scale_detail_id -- 量表详情id
scale_score_rules -- 量表评分规则
Return: scale_score_rules -- 量表编辑和更新后的评分规则
"""


def update_scale_score_rule(
    scale_detail_id: int,
    scale_score_rules: List[models.ScaleScoreRuleUpdate],
    session: Optional[SessionDep] = Session(engine),
):
    # 查询量表详情数据
    scale_detail = session.get(models.ScaleDetail, scale_detail_id)

    # 查询已存在的量表评分规则
    exist_rules = session.exec(
        select(models.ScaleScoreRule).where(
            models.ScaleScoreRule.scale_detail_id == scale_detail_id
        )
    ).all()

    # 删除已存在的量表评分规则
    if exist_rules:
        for exist_rule in exist_rules:
            if exist_rule.id not in [rule.id for rule in scale_score_rules]:
                session.delete(exist_rule)

    # 新增/编辑量表评分规则
    for rule in scale_score_rules:
        # 校验当前量表评分规则的scale_detail_id是否为当前量表详情id
        if rule.scale_detail_id != scale_detail_id:
            raise exception.create_http_exception(
                status_code=400,
                detail="量表评分规则的scale_detail_id与当前量表详情id不一致",
            )

        rule_merge = models.ScaleScoreRule(
            algorithm=rule.algorithm,
            id=rule.id,
            scale_detail_id=scale_detail_id,
        )

        session.merge(rule_merge)
        session.flush()  # 确保 rule_merge 的 id 被正确设置

        # 评分规则为T分算法
        if rule.algorithm == 1:
            # 查询已存在的量表评分计算规则逻辑列表
            exist_logics = session.exec(
                select(models.ScaleScoreRuleLogic).where(
                    models.ScaleScoreRuleLogic.scale_score_rule_id == rule_merge.id
                )
            ).all()

            # 删除已存在的量表评分计算规则逻辑列表
            if exist_logics:
                for exist_logic in exist_logics:
                    if exist_logic.id not in [logic.id for logic in rule.logics]:
                        session.delete(exist_logic)

            # 新增/编辑量表评分计算规则逻辑列表
            for logic in rule.logics:
                logic_merge = models.ScaleScoreRuleLogic(
                    start=logic.start,
                    start_include=logic.start_include,
                    end=logic.end,
                    end_include=logic.end_include,
                    description=logic.description,
                    id=logic.id,
                    rule=rule_merge,  # 确保 rule_merge 的 id 已经被设置
                )
                session.merge(logic_merge)

        # 评分规则为维度T分或多维T分算法
        elif rule.algorithm in [2, 3]:
            # 查询已存在的量表评分计算规则维度列表
            exist_dimensions = session.exec(
                select(models.ScaleScoreRuleDimension).where(
                    models.ScaleScoreRuleDimension.scale_score_rule_id == rule_merge.id
                )
            ).all()

            # 删除已存在的量表评分计算规则维度列表
            if exist_dimensions:
                for exist_dimension in exist_dimensions:
                    if exist_dimension.id not in [
                        dimension.id for dimension in rule.dimensions
                    ]:
                        session.delete(exist_dimension)

            # 新增/编辑量表评分计算规则维度列表
            for dimension in rule.dimensions:
                dimension_merge = models.ScaleScoreRuleDimension(
                    name=dimension.name,
                    order=dimension.order,
                    id=dimension.id,
                    rule=rule_merge,
                )
                session.merge(dimension_merge)
                session.flush()

                # 查询维度已关联的量表详情题目或者行列表
                exist_dimensions_ques_links = session.exec(
                    select(models.ScaleScoreRuleDimensionQuesLink).where(
                        models.ScaleScoreRuleDimensionQuesLink.dimension_id
                        == dimension.id
                    )
                )

                # 删除维度已关联的量表详情题目或者行列表
                if exist_dimensions_ques_links:
                    for exist_dimensions_ques_link in exist_dimensions_ques_links:
                        if exist_dimensions_ques_link.id not in [
                            link.id for link in dimension.dimensions_ques_links
                        ]:
                            session.delete(exist_dimensions_ques_link)

                # 新增/编辑维度关联的量表详情题目或者行列表
                for link in dimension.dimensions_ques_links:
                    link_merge = models.ScaleScoreRuleDimensionQuesLink(
                        ques_id=link.ques_id,
                        row_id=link.row_id,
                        id=link.id,
                        dimension=dimension_merge,
                    )
                    session.merge(link_merge)
                    session.flush()

                # 查询维度已关联的量表评分计算规则逻辑列表
                exist_dimension_logics = session.exec(
                    select(models.ScaleScoreRuleLogic).where(
                        models.ScaleScoreRuleLogic.dimension_id == dimension.id
                    )
                )

                # 删除维度已关联的量表评分计算规则逻辑列表
                if exist_dimension_logics:
                    for exist_dimension_logic in exist_dimension_logics:
                        if exist_dimension_logic.id not in [
                            logic.id for logic in dimension.logics
                        ]:
                            session.delete(exist_dimension_logic)

                # 新增/编辑维度关联的量表评分计算规则逻辑列表
                for logic in dimension.logics:
                    logic_merge = models.ScaleScoreRuleLogic(
                        classify=logic.classify,
                        start=logic.start,
                        start_include=logic.start_include,
                        end=logic.end,
                        end_include=logic.end_include,
                        description=logic.description,
                        id=logic.id,
                        dimension=dimension_merge,
                    )
                    session.merge(logic_merge)
                    session.flush()

        # 评分规则为自定义算法
        elif rule.algorithm == 4:
            # 查询已存在的量表评分计算规则自定义规则列表
            exist_custom_rules = session.exec(
                select(models.ScaleScoreRuleCustomRule).where(
                    models.ScaleScoreRuleCustomRule.scale_score_rule_id == rule_merge.id
                )
            )
            # 删除已存在的量表评分计算规则自定义规则列表
            if exist_custom_rules:
                for exist_custom_rule in exist_custom_rules:
                    if exist_custom_rule.id not in [
                        custom_rule.id for custom_rule in rule.custom_rules
                    ]:
                        session.delete(exist_custom_rule)

            # 新增/编辑量表评分计算规则自定义规则列表
            for custom_rule in rule.custom_rules:
                custom_rule_merge = models.ScaleScoreRuleCustomRule(
                    name=custom_rule.name,
                    order=custom_rule.order,
                    expression=custom_rule.expression,
                    id=custom_rule.id,
                    rule=rule_merge,
                )
                session.merge(custom_rule_merge)
                session.flush()

                # 查询自定义规则已关联的量表评分计算规则逻辑列表
                exist_custom_rule_logics = session.exec(
                    select(models.ScaleScoreRuleLogic).where(
                        models.ScaleScoreRuleLogic.custom_rule_id == custom_rule.id
                    )
                )

                # 删除自定义规则已关联的量表评分计算规则逻辑列表
                if exist_custom_rule_logics:
                    for exist_custom_rule_logic in exist_custom_rule_logics:
                        if exist_custom_rule_logic.id not in [
                            logic.id for logic in custom_rule.logics
                        ]:
                            session.delete(exist_custom_rule_logic)

                # 新增/编辑自定义规则关联的量表评分计算规则逻辑列表
                for logic in custom_rule.logics:
                    logic_merge = models.ScaleScoreRuleLogic(
                        classify=logic.classify,
                        start=logic.start,
                        start_include=logic.start_include,
                        end=logic.end,
                        end_include=logic.end_include,
                        description=logic.description,
                        id=logic.id,
                        custom_rule=custom_rule_merge,
                    )
                    session.merge(logic_merge)
                    session.flush()
    session.commit()

    # 查询最新量表评分规则数据
    scale_score_rules = session.exec(
        select(models.ScaleScoreRule).where(
            models.ScaleScoreRule.scale_detail_id == scale_detail_id
        )
    ).all()

    return scale_score_rules


"""拷贝量表评分规则

Keyword arguments:
scale_detail_id -- 量表详情id
Return: return_description
"""


def clone_scale_score_rule(
    scale_detail_id: int,
    session: Optional[SessionDep] = Session(engine),
):
    orginal_scale_score_rules = session.exec(
        select(models.ScaleScoreRule).where(
            models.ScaleScoreRule.scale_detail_id == scale_detail_id
        )
    ).all()

    # 拷贝量表评分规则
    for orginal_scale_score_rule in orginal_scale_score_rules:
        new_scale_score_rule = models.ScaleScoreRule(
            algorithm=orginal_scale_score_rule.algorithm,
            scale_detail_id=scale_detail_id,
        )

    # 新增量表评分规则
    for rule in scale_score_rules:
        # 新增量表评分规则数据
        rule_create = models.ScaleScoreRule(
            algorithm=rule.algorithm,
            scale_detail_id=scale_detail_id,
        )
        session.add(rule_create)
        session.flush()

        # 评分规则为T分算法
        if rule.algorithm == 1:
            # 新增量表评分计算规则逻辑列表
            for logic in rule.logics:
                logic_create = models.ScaleScoreRuleLogic(
                    start=logic.start,
                    start_include=logic.start_include,
                    end=logic.end,
                    end_include=logic.end_include,
                    description=logic.description,
                    rule=rule_create,
                )
                session.add(logic_create)
                session.flush()

        # 评分规则为维度T分或多维T分算法
        elif rule.algorithm in [2, 3]:
            # 新增量表评分计算规则维度列表
            for dimension in rule.dimensions:
                dimension_create = models.ScaleScoreRuleDimension(
                    name=dimension.name,
                    order=dimension.order,
                    rule=rule_create,
                )
                session.add(dimension_create)
                session.flush()

                # 新增维度关联的量表详情题目或者行列表
                for link in dimension.dimensions_ques_links:
                    link_create = models.ScaleScoreRuleDimensionQuesLink(
                        ques_id=link.ques_id,
                        row_id=link.row_id,
                        dimension=dimension_create,
                    )
                    session.add(link_create)
                    session.flush()

                # 新增维度关联的量表评分计算规则逻辑列表
                for logic in dimension.logics:
                    logic_create = models.ScaleScoreRuleLogic(
                        classify=logic.classify,
                        start=logic.start,
                        start_include=logic.start_include,
                        end=logic.end,
                        end_include=logic.end_include,
                        description=logic.description,
                        dimension=dimension_create,
                    )
                    session.add(logic_create)
                    session.flush()

        # 评分规则为自定义算法
        elif rule.algorithm == 4:
            # 新增量表评分计算规则自定义规则列表
            for custom_rule in rule.custom_rules:
                custom_rule_create = models.ScaleScoreRuleCustomRule(
                    name=custom_rule.name,
                    order=custom_rule.order,
                    expression=custom_rule.expression,
                    rule=rule_create,
                )
                session.add(custom_rule_create)
                session.flush()

                # 新增自定义规则关联的量表评分计算规则逻辑列表
                for logic in custom_rule.logics:
                    logic_create = models.ScaleScoreRuleLogic(
                        classify=logic.classify,
                        start=logic.start,
                        start_include=logic.start_include,
                        end=logic.end,
                        end_include=logic.end_include,
                        description=logic.description,
                        custom_rule=custom_rule_create,
                    )
                    session.add(logic_create)
                    session.flush()

    session.commit()

    # 查询最新量表评分规则数据
    scale_score_rules = session.exec(
        select(models.ScaleScoreRule).where(
            models.ScaleScoreRule.scale_detail_id == scale_detail_id
        )
    ).all()

    return scale_score_rules


"""发布量表详情

Keyword arguments:
scale_detail_id -- 量表详情id
Return: draft_scale_detail -- 新发布的量表详情数据(草稿状态)
"""


def publish_scale_detail(
    scale_detail_id: int,
    scale_score_rules: List[models.ScaleScoreRuleUpdate] = None,
    user: models.SystemUser = None,
    session: Optional[SessionDep] = Session(engine),
):
    try:
        # 获取原量表详情数据
        original_scale_detail = session.get(models.ScaleDetail, scale_detail_id)

        # 校验当前（源）量表是否存在
        if not original_scale_detail:
            raise exception.create_http_exception(status_code=400, detail="量表详情不存在")
        # 校验当前量表详情是否为草稿状态
        elif original_scale_detail.scale_link.status != 0:
            raise exception.create_http_exception(
                status_code=400, detail="发布失败，当前量表详情非草稿状态"
            )

        # 获取量表详情对应的量表
        scale = session.get(models.Scale, original_scale_detail.scale_id)

        """
        一、保存/更新量表评分规则
        """
        # 如果量表类型为1（基础量表）且有量表评分规则数据，保存量表评分规则
        if scale_score_rules and scale.type == 1:
            # 保存或更新量表评分规则
            scale_detail_rules_merge = update_scale_score_rule(
                scale_detail_id=scale_detail_id,
                scale_score_rules=scale_score_rules,
                session=session,
            )

        """
        二、将量表详情相关的数据拷贝一份
        """
        new_scale_detail = clone_scale_detail(scale_detail_id, session=session)

        """
        三、更新量表详情的状态为已发布
        """
        original_scale_detail.scale_link.status = 1
        session.merge(original_scale_detail)
        session.flush()

        """
        四、更新量表的更新人和更新时间
        """
        scale_id = original_scale_detail.scale_id
        scale = session.get(models.Scale, scale_id)
        if user is not None:
            scale.update_id = user.id
        scale.updatetime = datetime.datetime.now()
        session.merge(scale)
        session.flush()

        # 提交所有更改
        session.commit()

        return new_scale_detail


    except Exception as e:
        # 发生异常时回滚事务
        session.rollback()
        raise exception.create_http_exception(
            status_code=500, detail=f"{str(e)}"
        )
